package org.tinygame.herostory;

import com.google.protobuf.GeneratedMessageV3;
import com.google.protobuf.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tinygame.herostory.msg.GameMsgProtocol;

import java.lang.reflect.InvocationTargetException;
import java.rmi.MarshalledObject;
import java.util.HashMap;
import java.util.Map;

/**
 * @author anan
 * @create 2022-05-02 1:23
 */
public class GameMsgRecognizer {
    /**
     * 消息编号 -> 消息对象字典
     */
    static private final Map<Integer, GeneratedMessageV3> _msgCodeAndMsgObjMap = new HashMap<>();
    /**
     * 消息类 -> 消息编号字典
     */
    static private final Map<Class<?>, Integer> _clazzAndMsgCodeMap = new HashMap<>();

    static final private Logger LOGGER = LoggerFactory.getLogger(GameMsgRecognizer.class);

    private GameMsgRecognizer(){}

    static public void init(){

        LOGGER.info("--- 完成消息类与消息编号的映射 ===");
        Class<?>[] innerClazzArray = GameMsgProtocol.class.getDeclaredClasses();
        for(Class<?> innerClazz : innerClazzArray){
            if(null == innerClazz || !GeneratedMessageV3.class.isAssignableFrom(innerClazz)) continue;

            String clazzName = innerClazz.getSimpleName();
            clazzName = clazzName.toLowerCase();

            for(GameMsgProtocol.MsgCode msgCode : GameMsgProtocol.MsgCode.values()){
                if(null == msgCode) continue;

                String strMsgCode = msgCode.name();
                strMsgCode = strMsgCode.replaceAll("_", "");
                strMsgCode = strMsgCode.toLowerCase();

                if(!strMsgCode.startsWith(clazzName)) continue;

                try {
                    Object returnObj = innerClazz.getDeclaredMethod("getDefaultInstance").invoke(innerClazz);
                    LOGGER.info("{} <==> {}",
                            innerClazz.getName(),
                            msgCode.getNumber()
                    );
                    _msgCodeAndMsgObjMap.put(msgCode.getNumber(), (GeneratedMessageV3) returnObj);

                    _clazzAndMsgCodeMap.put(innerClazz, msgCode.getNumber());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }


/*        _msgCodeAndMsgObjMap.put(GameMsgProtocol.MsgCode.USER_ENTRY_CMD_VALUE, GameMsgProtocol.UserEntryCmd.getDefaultInstance());
        _msgCodeAndMsgObjMap.put(GameMsgProtocol.MsgCode.WHO_ELSE_IS_HERE_CMD_VALUE, GameMsgProtocol.WhoElseIsHereCmd.getDefaultInstance());
        _msgCodeAndMsgObjMap.put(GameMsgProtocol.MsgCode.USER_MOVE_TO_CMD_VALUE, GameMsgProtocol.UserMoveToCmd.getDefaultInstance());

        _clazzAndMsgCodeMap.put(GameMsgProtocol.UserEntryResult.class, GameMsgProtocol.MsgCode.USER_ENTRY_RESULT_VALUE);
        _clazzAndMsgCodeMap.put(GameMsgProtocol.WhoElseIsHereResult.class, GameMsgProtocol.MsgCode.WHO_ELSE_IS_HERE_RESULT_VALUE);
        _clazzAndMsgCodeMap.put(GameMsgProtocol.UserMoveToResult.class, GameMsgProtocol.MsgCode.USER_MOVE_TO_RESULT_VALUE);
        _clazzAndMsgCodeMap.put(GameMsgProtocol.UserQuitResult.class, GameMsgProtocol.MsgCode.USER_QUIT_RESULT_VALUE);*/
    }

    static public Message.Builder getBuilderByMsgCode(int msgCode){
        if(msgCode < 0) return null;

        GeneratedMessageV3 defaultMsg = _msgCodeAndMsgObjMap.get(msgCode);
        if(null == defaultMsg) return null;
        else return defaultMsg.newBuilderForType();
    }

    static public int getMsgCodeByClazz(Class<?> msgClazz) {
        if (null == msgClazz) {
            return -1;
        }

        Integer msgCode = _clazzAndMsgCodeMap.get(msgClazz);

        if (null == msgCode) {
            return -1;
        } else {
            return msgCode;
        }
    }

}
